#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <GL/glut.h>

#include "tocUtil.h"
#include "toc.h"

using namespace std;

static GLfloat scale = 1.0;
static GLint   viewStartx = -(MAP_W / 4 + 250); // To Focus the TOC area
static GLint   viewStarty = -(MAP_H / 4 + 60);  // To Focus the TOC area
static GLsizei viewWidth  = MAP_W;
static GLsizei viewHeight = MAP_H;
int pMouseX, pMouseY;
GLfloat c[4];

Toc *toc;

void processIdle(void)
{
	toc->processIdle();
}

void renderScene(void)
{
	glViewport(viewStartx, viewStarty, viewWidth, viewHeight);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();

	toc->renderObjects();

	glutSwapBuffers();
	glutPostRedisplay();
}

static inline void zoomIn(void)
{
	toc->changeMapScale(0.1);
	viewWidth  *= 1.1;
	viewHeight *= 1.1;
	viewStartx -= (viewWidth  / 20);
	viewStarty -= (viewHeight / 20);
}

static inline void zoomOut(void)
{
	if (viewWidth > TOC_W 
	    && viewHeight > TOC_H) {
		toc->changeMapScale(-0.1);
		viewWidth /= 1.1;
		viewHeight /= 1.1;
		viewStartx += (viewWidth / 20);
		viewStarty += (viewHeight / 20);
	}
}

void mouseHandler(int button, int state, int x, int y)
{
	if(state == GLUT_UP) {

///////////////////////

	GLfloat c[4];
	GLint v[4];
	GLdouble m[16], p[16];

	GLdouble xx, yy, zz;
	glGetDoublev(GL_MODELVIEW_MATRIX, m);
	glGetDoublev(GL_PROJECTION_MATRIX, p);
	glGetIntegerv(GL_VIEWPORT, v);

	gluProject(x, y, 1.0, m, p, v, &xx, &yy, &zz);
	glReadPixels(x, TOC_H - y, 1, 1, GL_RGBA, GL_FLOAT, c);
	cout << c[0] << ", " << c[1] << ", " << c[2] << endl;
////////////////////////////
		if (button == WHEEL_UP)
			zoomIn();
		else if (button == WHEEL_DOWN)
			zoomOut();
	}
}

void passiveMouseMotion(int x, int y)
{
	pMouseY = y;
	pMouseX = x;
}

void mouseMotion(int x, int y)
{
	viewStartx += (x - pMouseX);
	viewStarty += -(y - pMouseY);

	pMouseY = y;
	pMouseX = x;
}

void keyboard(unsigned char key, int x, int y)
{
	switch(key) {
	case 27:
		exit(0);
		break;

	case 'm':
		toc->toggleMapID();
		break;

	case 'y':
		zoomOut();
		break;

	case 'z':
		if(scale < 10) 
			zoomIn();
		break;

	default:
		break;
	}
}

void processMenuEvents(int option)
{

}

void createGlutMenus(void)
{
	int menu;

	menu = glutCreateMenu(processMenuEvents);

	glutAddMenuEntry("Red", 1);
	glutAddMenuEntry("Green", 2);
	glutAddMenuEntry("Blue", 3);

	glutAttachMenu(GLUT_RIGHT_BUTTON);
}

void init(void)
{
	toc->initialize();
}

void initApp(void)
{
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA);
	glutInitWindowSize(TOC_W, TOC_H);
	glutInitWindowPosition(TOC_STARTX, TOC_STARTY);
	glutCreateWindow("Taste Of Chicago");

	init();
}

void initCallbacks(void)
{
	glutKeyboardFunc(keyboard);
	glutMouseFunc(mouseHandler);
	glutPassiveMotionFunc(passiveMouseMotion);
	glutMotionFunc(mouseMotion);
	glutDisplayFunc(renderScene);
	glutIdleFunc(processIdle);

	createGlutMenus();
}

int main(int argc, char **argv)
{
	glutInit(&argc, argv);

	toc = new Toc();

	initApp();
	initCallbacks();

	glutMainLoop();

	return 0;
}
